dhcpv4: iface->dhcpv4_router -> iface->dhcpv4_routers
authorDavid Härdeman <[email protected]>
Sat, 22 Nov 2025 09:13:02 +0000 (10:13 +0100)
committerÁlvaro Fernández Rojas <[email protected]>
Thu, 27 Nov 2025 07:24:31 +0000 (08:24 +0100)
This makes it clearer that the variable stores multiple addresses, also
fix a potential realloc memleak.

Signed-off-by: David Härdeman <[email protected]>
Link: https://github.com/openwrt/odhcpd/pull/320
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
README.md
src/config.c
src/dhcpv4.c
src/odhcpd.h

index 2d8c3f2e5817f6613495cc61080f7c1b956e1547..663986a2874ace8e2c31621df973124c19137ba6 100644 (file)
--- a/README.md
+++ b/README.md
@@ -90,7 +90,7 @@ and may also receive information from ubus
 | dhcpv6_pd            |bool   | 1     | DHCPv6 stateful addressing hands out IA_PD - Internet Address - Prefix Delegation (PD) |
 | dhcpv6_pd_preferred   |bool | 0 | Set the DHCPv6-PD Preferred (P) flag in outgoing ICMPv6 RA message PIOs (RFC9762); requires `dhcpv6` and `dhcpv6_pd`. |
 | dhcpv6_pd_min_len    |integer| -     | Minimum prefix length to delegate with IA_PD (value is adjusted if needed to be greater than the interface prefix length).  Range [1,62] |
-| router               |list   |`<local address>`| Routers to announce, accepts IPv4 only |
+| router               |list   |`<local address>`| IPv4 addresses of routers on a given subnet (provided via DHCPv4, should be in order of preference) |
 | dns                  |list   |`<local address>`| DNS servers to announce, accepts IPv4 and IPv6 |
 | dnr                  |list   |disabled| Encrypted DNS servers to announce, `<priority> <domain name> [<comma separated IP addresses> <SvcParams (key=value)>...]` |
 | dns_service          |bool   | 1     | Announce the address of interface as DNS service if the list of dns is empty |
index 30609a63dccede6527b79b243d957ead1a9b34be..68ef3abcfff16cc45b4247cb03a8f82d6bbac143 100644 (file)
@@ -346,7 +346,7 @@ static void clean_interface(struct interface *iface)
        free(iface->dns_addrs6);
        free(iface->dns_search);
        free(iface->upstream);
-       free(iface->dhcpv4_router);
+       free(iface->dhcpv4_routers);
        free(iface->dhcpv6_raw);
        free(iface->dhcpv4_ntp);
        free(iface->dhcpv6_ntp);
@@ -1291,21 +1291,23 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr
                unsigned rem;
 
                blobmsg_for_each_attr(cur, c, rem) {
-                       struct in_addr addr4;
+                       struct in_addr addr4, *tmp;
 
                        if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false))
                                continue;
 
                        if (inet_pton(AF_INET, blobmsg_get_string(cur), &addr4) == 1) {
-                               iface->dhcpv4_router = realloc(iface->dhcpv4_router,
-                                               (++iface->dhcpv4_router_cnt) * sizeof(*iface->dhcpv4_router));
-                               if (!iface->dhcpv4_router)
+                               tmp = realloc(iface->dhcpv4_routers,
+                                             (iface->dhcpv4_routers_cnt + 1) * sizeof(*iface->dhcpv4_routers));
+                               if (!tmp)
                                        goto err;
 
-                               iface->dhcpv4_router[iface->dhcpv4_router_cnt - 1] = addr4;
-                       } else
+                               iface->dhcpv4_routers = tmp;
+                               iface->dhcpv4_routers[iface->dhcpv4_routers_cnt++] = addr4;
+                       } else {
                                error("Invalid %s value configured for interface '%s'",
                                      iface_attrs[IFACE_ATTR_ROUTER].name, iface->name);
+                       }
                }
        }
 
index 545c8142b9d6fecb3a4227b4c3fcde4188ebcb1a..97c1ec2bb739c5f8fd9423177ab367641f501aaa 100644 (file)
@@ -1094,9 +1094,9 @@ void dhcpv4_handle_msg(void *src_addr, void *data, size_t len,
 
                case DHCPV4_OPT_ROUTER:
                        iov[IOV_ROUTER].iov_len = sizeof(reply_router);
-                       if (iface->dhcpv4_router_cnt) {
-                               reply_router.len = iface->dhcpv4_router_cnt * sizeof(*iface->dhcpv4_router);
-                               iov[IOV_ROUTER_ADDR].iov_base = iface->dhcpv4_router;
+                       if (iface->dhcpv4_routers_cnt) {
+                               reply_router.len = iface->dhcpv4_routers_cnt * sizeof(*iface->dhcpv4_routers);
+                               iov[IOV_ROUTER_ADDR].iov_base = iface->dhcpv4_routers;
                        } else {
                                reply_router.len = sizeof(iface->dhcpv4_own_ip.addr.in);
                                iov[IOV_ROUTER_ADDR].iov_base = &iface->dhcpv4_own_ip.addr.in;
index a74c295cc7815a4324db7369571a8d05eec0dfbd..a5ba49695ec7d376195d152b8c60178a23f1fadf 100644 (file)
@@ -447,8 +447,8 @@ struct interface {
        struct in_addr dhcpv4_start_ip;
        struct in_addr dhcpv4_end_ip;
        struct odhcpd_ipaddr dhcpv4_own_ip;
-       struct in_addr *dhcpv4_router;
-       size_t dhcpv4_router_cnt;
+       struct in_addr *dhcpv4_routers; // IPv4 addresses for routers on this subnet
+       size_t dhcpv4_routers_cnt;      // Count of router addresses
        bool dhcpv4_forcereconf;
 
        // DNS